package cn.jhz.learn.community_dynamic.app.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import cn.jhz.learn.community_dynamic.CommunityDynamicApplication;
import cn.jhz.learn.community_dynamic.common.bean.JsonData;
import cn.jhz.learn.community_dynamic.common.exception.RequestException;
import cn.jhz.learn.community_dynamic.common.util.VerifyHelper;
import cn.jhz.learn.community_dynamic.dao.CommentJpaRepository;
import cn.jhz.learn.community_dynamic.dao.ImageJpaRepository;
import cn.jhz.learn.community_dynamic.dao.PostClassJpaRepository;
import cn.jhz.learn.community_dynamic.dao.PostJpaRepository;
import cn.jhz.learn.community_dynamic.dao.TopicJpaRepository;
import cn.jhz.learn.community_dynamic.manager.PostManager;
import cn.jhz.learn.community_dynamic.model.ImageEntity;
import cn.jhz.learn.community_dynamic.model.PostClassEntity;
import cn.jhz.learn.community_dynamic.model.PostEntity;
import cn.jhz.learn.community_dynamic.model.TopicEntity;
import cn.jhz.learn.community_dynamic.model.UserEntity;
import cn.jhz.learn.community_dynamic.qo.PostSubmit;
import cn.jhz.learn.community_dynamic.security.helper.LoginHelper;
import cn.jhz.learn.community_dynamic.service.ImageService;
import cn.jhz.learn.community_dynamic.service.PostService;
import cn.jhz.learn.community_dynamic.vo.app.PostView;

import lombok.Getter;

@RestController
@RequestMapping("api/")
public class ContentController {
    private final PostClassJpaRepository postClassJpaRepository;
    private final ImageJpaRepository imageJpaRepository;
    private final TopicJpaRepository topicJpaRepository;
    private final PostJpaRepository postJpaRepository;
    private final CommentJpaRepository commentJpaRepository;

    private final PostManager postManager;
    private final ImageService fileService;
    private final PostService postService;

    static private final List<Byte> publicStatus = Arrays.asList((byte) 1);
    static private final List<Byte> publicOpens = Arrays.asList((byte) 1);

    @Getter
    private class ImageView {
	private String url;
	private Long user_id;
	private Date create_time;
	private Date update_time;
	private Integer id;

	private ImageView(ImageEntity entity) {
	    this.url = entity.getUrl();
	    this.user_id = entity.getUser().getLoginId();
	    this.create_time = entity.getCreateTime();
	    this.update_time = entity.getCreateTime();
	    this.id = entity.getId();
	}
    }

    @Autowired
    public ContentController(PostClassJpaRepository postClassJpaRepository, ImageJpaRepository imageJpaRepository,
	    PostJpaRepository postJpaRepository, TopicJpaRepository topicJpaRepository,
	    CommentJpaRepository commentJpaRepository, PostManager postManager, ImageService fileService,
	    PostService postService) {
	super();
	this.postClassJpaRepository = postClassJpaRepository;
	this.imageJpaRepository = imageJpaRepository;
	this.topicJpaRepository = topicJpaRepository;
	this.postJpaRepository = postJpaRepository;
	this.commentJpaRepository = commentJpaRepository;
	this.postManager = postManager;
	this.fileService = fileService;
	this.postService = postService;
    }

    @PostMapping(value = "auth/image/upload_more")
    @PreAuthorize("hasAuthority('file::batch_upload')")
    public JsonData uploadMore(@RequestParam("imgList") List<MultipartFile> files) {
	
	List<ImageEntity> entities = this.fileService.batchUpload(files);
	
	this.fileService.getReviewCache(CommunityDynamicApplication.REVIEW_CACHE).get().addAll(entities.stream().map(ImageEntity::getId).collect(Collectors.toList()));
	
	return JsonData.newSuccessInstance(entities.stream().map(ImageView::new).collect(Collectors.toList()));
    }

    @PostMapping("auth/post/create")
    @PreAuthorize("hasAuthority('post::create')")
    public JsonData create(@RequestBody PostSubmit parameter) {
	/**
	 * 获取用户id 检查图片是否存在 检查topic是否存在 检查class是否存在
	 */
	// TODO 修改前端用户id
	Integer userId = ((UserEntity) LoginHelper.getLoginUser().get()).getId();

	VerifyHelper.createVerify(parameter, PostSubmit.ParamType.values(), (paramType) -> {
	    switch (paramType) {
	    case img_id_list:
		if (parameter.getImgIdList().size() == this.imageJpaRepository.countByUser_idAndIdIn(userId,
			parameter.getImgIdList())) {
		    break;
		} else {
		    throw new RequestException("图片不合法!");
		}
	    case topic_id:
		if (this.topicJpaRepository.existsById(parameter.getTopicId())) {
		    break;
		} else {
		    throw new RequestException("话题不存在!");
		}
	    case post_class_id:
		if (this.postClassJpaRepository.existsById(parameter.getPostClassId())) {
		    break;
		} else {
		    throw new RequestException("分类不存在!");
		}
	    case text:
		// TODO 校验文本内容
		break;
	    default:
		break;
	    }
	});

	PostEntity postEntity = this.postManager.addInstance(PostEntity.builder().createTime(new Date())
		.content(parameter.getText())
		.images(new HashSet<>(this.imageJpaRepository.findAllById(parameter.getImgIdList()))).type((byte) 0)
		.user((UserEntity) LoginHelper.getLoginUser().get()).isOpen(parameter.getIsOpen())
		.topics(new HashSet<>(Arrays.asList(this.topicJpaRepository.findById(parameter.getTopicId()).get())))
		.status((byte) 1).postClass(this.postClassJpaRepository.findById(parameter.getPostClassId()).get())
		.shareCount(0).path("未知").title("").titlepic("").build());

	if (parameter.getIsOpen().equals((byte) 1)) {
	    List<Integer> cache = this.postService.getReviewCache(CommunityDynamicApplication.REVIEW_CACHE).get();

	    cache.add(this.postService.review(postEntity).getId());

	    this.postService.putReviewCache(CommunityDynamicApplication.REVIEW_CACHE, cache);
	}

	return JsonData.newSuccessInstance();
    }

    @GetMapping("post/{id}")
    public JsonData get(@PathVariable("id") Integer id) {
	/**
	 * 1. 直接根据id、status获取文章，并进行非空检查 2. 尝试获取请求者 3. 若文章非公开，条件2存在，进行判断，请求者是否拥有该文章
	 */
	PostEntity entity = this.postJpaRepository.findByIdAndStatus(id, (byte) 1)
		.orElseThrow(() -> new RequestException("文章不存在!"));
	Optional<?> requester = LoginHelper.getLoginUser();

	// 判断文章权限
	if (entity.getIsOpen().equals((byte) 0)) {
	    Integer userId = ((UserEntity) requester.orElseThrow(() -> new RequestException("请先登录!"))).getId();
	    if (!userId.equals(entity.getUser().getId())) {
		throw new RequestException("权限不足!");
	    }
	}

	Map<String, Object> detail = new HashMap<>();
	detail.put("content", entity.getContent());
	detail.put("images", entity.getImages().parallelStream().map(ImageView::new).collect(Collectors.toList()));

	return JsonData.newSuccessInstance(detail);
    }

    @GetMapping("post_class/{id}/post/{page}")
    public JsonData getPageByCategory(@PathVariable("id") Integer classId, @PathVariable("page") Integer page) {
	Optional<PostClassEntity> classEntityOptional = this.postClassJpaRepository.findById(classId);

	return JsonData.newSuccessInstance(this.postJpaRepository
		.findByPostClassAndStatusInAndIsOpenIn(
			classEntityOptional.orElseThrow(() -> new RequestException("无效主题")), publicStatus, publicOpens,
			PageRequest.of(page - 1, 10))
		.stream()
		.map(entity -> PostView.classPageView(entity,
			this.postJpaRepository.countSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.postJpaRepository.countUnSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.commentJpaRepository.countByPostAndStatus(entity, (byte) 1)))
		.collect(Collectors.toList()));
    }

    @GetMapping("topic/{id}/post/{page}")
    public JsonData getPageByTopic(@PathVariable("id") Integer id, @PathVariable("page") Integer page) {
	Optional<TopicEntity> entityOptional = this.topicJpaRepository.findById(id);
	return JsonData.newSuccessInstance(this.postJpaRepository
		.findByTopicsAndStatusInAndIsOpenIn(entityOptional.orElseThrow(() -> new RequestException("无效主题")),
			publicStatus, publicOpens, PageRequest.of(page - 1, 10))
		.stream()
		.map(entity -> PostView.classPageView(entity,
			this.postJpaRepository.countSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.postJpaRepository.countUnSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.commentJpaRepository.countByPostAndStatus(entity, (byte) 1)))
		.collect(Collectors.toList()));
    }

    @GetMapping("user/{id}/post/{page}")
    public JsonData getPageByUser(@PathVariable("id") Long id, @PathVariable("page") Integer page) {
	/**
	 * 1.判断是匿名访问，还是用户访问 2.获取访问者信息 3.进行判断，确定isOpen TODO 缺少参数校验
	 */
	Optional<?> requester = LoginHelper.getLoginUser();
	List<Byte> isOpen = new ArrayList<>();
	isOpen.add((byte) 1);
	if (requester.isPresent()) {
	    if (((UserEntity) requester.get()).getLoginId().equals(id)) {
		isOpen.add((byte) 0);
	    }
	}

	return JsonData.newSuccessInstance(this.postJpaRepository
		.findByUser_loginIdAndStatusAndIsOpenIn(id, (byte) 1, isOpen, PageRequest.of(page - 1, 10)).stream()
		.map(entity -> PostView.classPageView(entity,
			this.postJpaRepository.countSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.postJpaRepository.countUnSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.commentJpaRepository.countByPostAndStatus(entity, (byte) 1)))
		.collect(Collectors.toList()));
    }

    @GetMapping("search/post")
    public JsonData searchPost(@RequestParam("keyword") String keyword, @RequestParam("page") Integer page) {

	return JsonData.newSuccessInstance(this.postJpaRepository
		.findByStatusAndIsOpenAndTitleContainingOrContentContaining((byte) 1, (byte) 1, keyword, keyword,
			PageRequest.of(page - 1, 10))
		.stream()
		.map(entity -> PostView.classPageView(entity,
			this.postJpaRepository.countSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.postJpaRepository.countUnSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
			this.commentJpaRepository.countByPostAndStatus(entity, (byte) 1)))
		.collect(Collectors.toList()));
    }

    @GetMapping("auth/follow_post/{page}")
    @PreAuthorize("hasAuthority('post::get_follow')")
    public JsonData getPageByFollow(@PathVariable("page") Integer page) {
	/**
	 * 1.判断是匿名访问，还是用户访问 2.获取访问者信息 3.进行判断，确定isOpen
	 */
	Optional<?> requester = LoginHelper.getLoginUser();

	return JsonData
		.newSuccessInstance(
			this.postJpaRepository
				.findByUser_followedsAndStatusAndIsOpen(
					(UserEntity) requester.get(), (byte) 1, (byte) 0, PageRequest.of(page - 1, 10))
				.stream()
				.map(entity -> PostView.classPageView(entity,
					this.postJpaRepository.countSupportUsersByIdAndStatus(entity.getId(), (byte) 1),
					this.postJpaRepository.countUnSupportUsersByIdAndStatus(entity.getId(),
						(byte) 1),
					this.commentJpaRepository.countByPostAndStatus(entity, (byte) 1)))
				.collect(Collectors.toList()));
    }
}
